package com.miracle9.game.dao;

import com.miracle9.game.bean.Pager;
import org.apache.commons.lang.StringUtils;
import org.hibernate.Query;
import org.hibernate.SQLQuery;
import org.hibernate.Session;
import org.hibernate.SessionFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.util.Assert;

import java.io.Serializable;
import java.lang.reflect.ParameterizedType;
import java.lang.reflect.Type;
import java.util.List;

public class SqlOperating<E, PK extends Serializable> {

    @Autowired
    private SessionFactory sessionFactory;
    private Class<E> classE;

    public SqlOperating() {
        this.classE = null;
        Class c = getClass();
        Type type = c.getGenericSuperclass();
        if ((type instanceof ParameterizedType)) {
            Type[] parameterizedType = ((ParameterizedType) type).getActualTypeArguments();
            this.classE = ((Class) parameterizedType[0]);
        }
    }

    protected Session getSession() {
        return this.sessionFactory.getCurrentSession();
    }

    public Object getById(PK id) {
        Assert.notNull(id, "id is required");
        return getSession().get(this.classE, id);
    }

    public Serializable saveReturn(E entity) {
        Assert.notNull(entity, "entity is required");
        return getSession().save(entity);
    }

    public void save(E entity) {
        Assert.notNull(entity, "entity is required");
        getSession().save(entity);
    }

    public void saveOrUpdate(E entity) {
        Assert.notNull(entity, "entity is required");
        getSession().saveOrUpdate(entity);
    }

    public void update(E entity) {
        Assert.notNull(entity, "entity is required");
        getSession().merge(entity);
    }

    public void delete(E entity) {
        Assert.notNull(entity, "entity is required");
        getSession().delete(entity);
    }

    public void deleteById(PK id) {
        Assert.notNull(id, "id is required");
        Object entity = getById(id);
        getSession().delete(entity);
    }

    public void deleteByIds(PK[] ids) {
        Assert.notEmpty(ids, "ids must not be empty");
        for (PK id : ids) {
            Object entity = getById(id);
            getSession().delete(entity);
        }
    }

    public Query q_CreateSql(String hql, Object[] params) {
        Assert.hasText(hql, "queryString不能为空");
        Query query = getSession().createQuery(hql);
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        return query;
    }

    public SQLQuery s_CreateSql(String sql, Object[] params) {
        Assert.hasText(sql, "queryString不能为空");
        SQLQuery query = getSession().createSQLQuery(sql);
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        return query;
    }

    public List<E> q_CreateSqlList(String hql, Object[] params) {
        Assert.hasText(hql, "hql不能为空");
        Query query = getSession().createQuery(hql);
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        return query.list();
    }

    public List<E> s_CreateSqlList(String sql, Object[] params) {
        Assert.hasText(sql, "hql不能为空");
        SQLQuery query = getSession().createSQLQuery(sql);
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        query.addEntity(this.classE);
        return query.list();
    }

    public Pager q_CreateSqlsPager(String hql, Pager pager, Object[] params) {
        Assert.hasText(hql, "hql不能为空");
        Query countQuery = getSession().createQuery("select count(*) " + hql);
        if (StringUtils.isNotBlank(pager.getOrderBy())) {
            hql = hql + " order by " + pager.getOrderBy();
        }
        if (StringUtils.isNotBlank(pager.getOrder())) {
            hql = hql + " " + pager.getOrder();
        }
        Query query = getSession().createQuery(hql);
        query.setFirstResult((pager.getPageNumber() - 1) * pager.getPageSize());
        query.setMaxResults(pager.getPageSize());
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
                countQuery.setParameter(i, params[i]);
            }
        }
        pager.setTotalCount(Integer.parseInt(countQuery.uniqueResult().toString()));
        pager.setList(query.list().toArray());
        return pager;
    }

    public Pager s_CreateSqlsPager(String sql, Pager pager, Object[] params) {
        Assert.hasText(sql, "hql不能为空");
        Query countQuery = getSession().createSQLQuery("select count(*) from (" + sql + ") t");
        if (StringUtils.isNotBlank(pager.getOrderBy())) {
            sql = sql + " order by " + pager.getOrderBy();
        }
        if (StringUtils.isNotBlank(pager.getOrder())) {
            sql = sql + " " + pager.getOrder();
        }
        SQLQuery query = getSession().createSQLQuery(sql);
        query.setFirstResult((pager.getPageNumber() - 1) * pager.getPageSize());
        query.setMaxResults(pager.getPageSize());
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
                countQuery.setParameter(i, params[i]);
            }
        }
        query.addEntity(this.classE);
        pager.setTotalCount(Integer.parseInt(countQuery.uniqueResult().toString()));
        pager.setList(query.list().toArray());
        return pager;
    }

    public E q_CreateSqlFilter(String hql, Object[] params) {
        Assert.hasText(hql, "hql不能为空");
        Query query = getSession().createQuery(hql);
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        List es = query.list();
        return (E) (es.isEmpty() ? null : es.get(0));
    }

    public int q_CreateSqlInt(String hql, Object[] params) {
        Assert.hasText(hql, "hql不能为空");
        Query query = getSession().createQuery(hql);
        if (params != null) {
            for (int i = 0; i < params.length; i++) {
                query.setParameter(i, params[i]);
            }
        }
        Object o = query.uniqueResult();
        return ((Number) query.uniqueResult()).intValue();
    }

    public int q_Update(String hql, Object[] params) {
        Query query = q_CreateSql(hql, params);
        return query.executeUpdate();
    }

}